--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
tests/backend/test_telephone_recorder.py ef7f42c190120a5fa884acb5595ea8dcc93b3aaa (ef7f42c1) Text, 6.46 KB
T8b949e# SPDX-License-Identifier: 0BSD
Tff7b72import T7ee787os
Tff7b72import T7ee787time
Tff7b72from T7ee787unittestT7ee787.T7ee787mock Tff7b72import Te6edf3MagicMockTb4b4b4, Te6edf3patch
Tff7b72import T7ee787pytest
Tff7b72import T7ee787RNS
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787telephone_manager Tff7b72import Te6edf3TelephoneManager
Tf0883e@pytestTff7b72.Td2a8fffixture
Tff7b72def Td2a8ffmock_identityTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3mock_id Tff7b72= Te6edf3MagicMockTb4b4b4(Te6edf3specTff7b72=Te6edf3RNSTff7b72.Td2a8ffIdentityTb4b4b4)
Te6edf3mock_idTff7b72.Td2a8ffhash Tff7b72= Ta5d6ffbTa5d6ff"Ta5d6fftest_identity_hash_32_bytes_longTa5d6ff"
Tff7b72return Te6edf3mock_id
Tf0883e@pytestTff7b72.Td2a8fffixture
Tff7b72def Td2a8ffmock_configTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3config Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3configTff7b72.Td2a8ffcall_recording_enabledTff7b72.Td2a8ffgetTff7b72.Td2a8ffreturn_value Tff7b72= Tff7b72True
Te6edf3configTff7b72.Td2a8fftelephone_audio_profile_idTff7b72.Td2a8ffgetTff7b72.Td2a8ffreturn_value Tff7b72= T79c0ff2
Tff7b72return Te6edf3config
Tf0883e@pytestTff7b72.Td2a8fffixture
Tff7b72def Td2a8ffmock_dbTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Tf0883e@pytestTff7b72.Td2a8fffixture
Tff7b72def Td2a8fftemp_storageTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Te6edf3storage_dir Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffstorageTa5d6ff"
Te6edf3storage_dirTff7b72.Td2a8ffmkdirTb4b4b4(Tb4b4b4)
Tff7b72return Tffa657strTb4b4b4(Te6edf3storage_dirTb4b4b4)
Tff7b72def Td2a8fftest_telephone_manager_initTb4b4b4(Te6edf3mock_identityTb4b4b4, Te6edf3mock_configTb4b4b4, Te6edf3temp_storageTb4b4b4)Tb4b4b4:
Te6edf3tm Tff7b72= Te6edf3TelephoneManagerTb4b4b4(
Te6edf3mock_identityTb4b4b4,
Te6edf3config_managerTff7b72=Te6edf3mock_configTb4b4b4,
Te6edf3storage_dirTff7b72=Te6edf3temp_storageTb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3tmTff7b72.Td2a8ffidentity Tff7b72== Te6edf3mock_identity
Tff7b72assert Te6edf3tmTff7b72.Td2a8ffconfig_manager Tff7b72== Te6edf3mock_config
Tff7b72assert Te6edf3tmTff7b72.Td2a8ffstorage_dir Tff7b72== Te6edf3temp_storage
Tff7b72assert Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3tmTff7b72.Td2a8ffrecordings_dirTb4b4b4)
Tf0883e@patchTb4b4b4(Ta5d6ff"Ta5d6ffmeshchatx.src.backend.telephone_manager.TelephoneTa5d6ff"Tb4b4b4)
Tff7b72def Td2a8fftest_call_recording_lifecycleTb4b4b4(
Te6edf3mock_telephone_classTb4b4b4,
Te6edf3mock_identityTb4b4b4,
Te6edf3mock_configTb4b4b4,
Te6edf3mock_dbTb4b4b4,
Te6edf3temp_storageTb4b4b4,
Tb4b4b4)Tb4b4b4:
T8b949e# Setup mocks
Te6edf3mock_telephone Tff7b72= Te6edf3mock_telephone_classTff7b72.Td2a8ffreturn_value
Te6edf3mock_active_call Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3mock_remote_identity Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3mock_remote_identityTff7b72.Td2a8ffhash Tff7b72= Ta5d6ffbTa5d6ff"Ta5d6ffremote_hash_32_bytes_long_012345Ta5d6ff"
Te6edf3mock_active_callTff7b72.Td2a8ffget_remote_identityTff7b72.Td2a8ffreturn_value Tff7b72= Te6edf3mock_remote_identity
Te6edf3mock_telephoneTff7b72.Td2a8ffactive_call Tff7b72= Te6edf3mock_active_call
T8b949e# Mock mixers
Te6edf3mock_telephoneTff7b72.Td2a8ffreceive_mixer Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3mock_telephoneTff7b72.Td2a8fftransmit_mixer Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3tm Tff7b72= Te6edf3TelephoneManagerTb4b4b4(
Te6edf3mock_identityTb4b4b4,
Te6edf3config_managerTff7b72=Te6edf3mock_configTb4b4b4,
Te6edf3storage_dirTff7b72=Te6edf3temp_storageTb4b4b4,
Te6edf3dbTff7b72=Te6edf3mock_dbTb4b4b4,
Tb4b4b4)
Te6edf3tmTff7b72.Td2a8ffget_name_for_identity_hash Tff7b72= Te6edf3MagicMockTb4b4b4(Te6edf3return_valueTff7b72=Ta5d6ff"Ta5d6ffRemote UserTa5d6ff"Tb4b4b4)
Te6edf3tmTff7b72.Td2a8ffinit_telephoneTb4b4b4(Tb4b4b4)
T8b949e# Simulate call established
Te6edf3tmTff7b72.Td2a8ffon_telephone_call_establishedTb4b4b4(Te6edf3mock_remote_identityTb4b4b4)
T8b949e# Verify recording NOT started (disabled for now)
Tff7b72assert Tff7b72not Te6edf3tmTff7b72.Td2a8ffis_recording
T8b949e# assert mock_sink.call_count == 0 # RX and TX sinks not created
T8b949e# assert mock_sink.return_value.start.called # Autodigest handled by monkey patch in meshchat.py
T8b949e# Simulate call ended after some time
Te6edf3tmTff7b72.Td2a8ffrecording_start_time Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4) Tff7b72- T79c0ff5 T8b949e# 5 seconds duration
T8b949e# tm.is_recording = True # Force recording state for test (Disabled for now as property has no setter)
Te6edf3tmTff7b72.Td2a8ffrecording_remote_identity Tff7b72= Te6edf3mock_remote_identity
Te6edf3tmTff7b72.Td2a8ffon_telephone_call_endedTb4b4b4(Te6edf3mock_remote_identityTb4b4b4)
T8b949e# Verify recording stopped and saved to DB
Tff7b72assert Tff7b72not Te6edf3tmTff7b72.Td2a8ffis_recording
T8b949e# assert mock_db.telephone.add_call_recording.called # Disabled for now as recording is disabled
Tff7b72def Td2a8fftest_call_recording_disabledTb4b4b4(Te6edf3mock_identityTb4b4b4, Te6edf3mock_configTb4b4b4, Te6edf3mock_dbTb4b4b4, Te6edf3temp_storageTb4b4b4)Tb4b4b4:
Te6edf3mock_configTff7b72.Td2a8ffcall_recording_enabledTff7b72.Td2a8ffgetTff7b72.Td2a8ffreturn_value Tff7b72= Tff7b72False
Te6edf3tm Tff7b72= Te6edf3TelephoneManagerTb4b4b4(
Te6edf3mock_identityTb4b4b4,
Te6edf3config_managerTff7b72=Te6edf3mock_configTb4b4b4,
Te6edf3storage_dirTff7b72=Te6edf3temp_storageTb4b4b4,
Te6edf3dbTff7b72=Te6edf3mock_dbTb4b4b4,
Tb4b4b4)
T8b949e# Mock telephone and active call
Te6edf3tmTff7b72.Td2a8fftelephone Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3tmTff7b72.Td2a8fftelephoneTff7b72.Td2a8ffactive_call Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3tmTff7b72.Td2a8ffon_telephone_call_establishedTb4b4b4(Te6edf3MagicMockTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72assert Tff7b72not Te6edf3tmTff7b72.Td2a8ffis_recording
Tff7b72assert Tff7b72not Te6edf3mock_dbTff7b72.Td2a8fftelephoneTff7b72.Td2a8ffadd_call_recordingTff7b72.Td2a8ffcalled
Tff7b72def Td2a8fftest_audio_profile_persistenceTb4b4b4(Te6edf3mock_identityTb4b4b4, Te6edf3mock_configTb4b4b4, Te6edf3temp_storageTb4b4b4)Tb4b4b4:
Tff7b72with Te6edf3patchTb4b4b4(
Ta5d6ff"Ta5d6ffmeshchatx.src.backend.telephone_manager.TelephoneTa5d6ff"Tb4b4b4,
Tb4b4b4) Tff7b72as Te6edf3mock_telephone_classTb4b4b4:
Te6edf3mock_telephone Tff7b72= Te6edf3mock_telephone_classTff7b72.Td2a8ffreturn_value
Te6edf3mock_configTff7b72.Td2a8fftelephone_audio_profile_idTff7b72.Td2a8ffgetTff7b72.Td2a8ffreturn_value Tff7b72= T79c0ff4
Te6edf3tm Tff7b72= Te6edf3TelephoneManagerTb4b4b4(
Te6edf3mock_identityTb4b4b4,
Te6edf3config_managerTff7b72=Te6edf3mock_configTb4b4b4,
Te6edf3storage_dirTff7b72=Te6edf3temp_storageTb4b4b4,
Tb4b4b4)
Te6edf3tmTff7b72.Td2a8ffinit_telephoneTb4b4b4(Tb4b4b4)
T8b949e# Verify switch_profile was called with configured ID
Te6edf3mock_telephoneTff7b72.Td2a8ffswitch_profileTff7b72.Td2a8ffassert_called_withTb4b4b4(T79c0ff4Tb4b4b4)
Tf0883e@patchTb4b4b4(Ta5d6ff"Ta5d6ffmeshchatx.src.backend.telephone_manager.TelephoneTa5d6ff"Tb4b4b4)
Tff7b72def Td2a8fftest_call_recording_saves_after_disconnectTb4b4b4(
Te6edf3mock_telephone_classTb4b4b4,
Te6edf3mock_identityTb4b4b4,
Te6edf3mock_configTb4b4b4,
Te6edf3mock_dbTb4b4b4,
Te6edf3temp_storageTb4b4b4,
Tb4b4b4)Tb4b4b4:
T8b949e# Setup mocks
Te6edf3mock_telephone Tff7b72= Te6edf3mock_telephone_classTff7b72.Td2a8ffreturn_value
Te6edf3mock_active_call Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3mock_remote_identity Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3mock_remote_identityTff7b72.Td2a8ffhash Tff7b72= Ta5d6ffbTa5d6ff"Ta5d6ffremote_hash_32_bytes_long_012345Ta5d6ff"
Te6edf3mock_active_callTff7b72.Td2a8ffget_remote_identityTff7b72.Td2a8ffreturn_value Tff7b72= Te6edf3mock_remote_identity
Te6edf3mock_telephoneTff7b72.Td2a8ffactive_call Tff7b72= Te6edf3mock_active_call
T8b949e# Mock mixers
Te6edf3mock_telephoneTff7b72.Td2a8ffreceive_mixer Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3mock_telephoneTff7b72.Td2a8fftransmit_mixer Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3tm Tff7b72= Te6edf3TelephoneManagerTb4b4b4(
Te6edf3mock_identityTb4b4b4,
Te6edf3config_managerTff7b72=Te6edf3mock_configTb4b4b4,
Te6edf3storage_dirTff7b72=Te6edf3temp_storageTb4b4b4,
Te6edf3dbTff7b72=Te6edf3mock_dbTb4b4b4,
Tb4b4b4)
Te6edf3tmTff7b72.Td2a8ffinit_telephoneTb4b4b4(Tb4b4b4)
T8b949e# Start recording
Te6edf3tmTff7b72.Td2a8ffstart_recordingTb4b4b4(Tb4b4b4)
Tff7b72assert Tff7b72not Te6edf3tmTff7b72.Td2a8ffis_recording T8b949e# Disabled for now
T8b949e# Force recording state for test
T8b949e# tm.is_recording = True (Disabled for now as property has no setter)
Te6edf3tmTff7b72.Td2a8ffrecording_remote_identity Tff7b72= Te6edf3mock_remote_identity
T8b949e# Simulate call disconnected (active_call becomes None)
Te6edf3mock_telephoneTff7b72.Td2a8ffactive_call Tff7b72= Tff7b72None
T8b949e# End recording (simulate call ended callback)
Te6edf3tmTff7b72.Td2a8ffrecording_start_time Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4) Tff7b72- T79c0ff5
Te6edf3tmTff7b72.Td2a8ffon_telephone_call_endedTb4b4b4(Te6edf3mock_remote_identityTb4b4b4)
T8b949e# Verify it still saved using the captured identity
Tff7b72assert Tff7b72not Te6edf3tmTff7b72.Td2a8ffis_recording
T8b949e# assert mock_db.telephone.add_call_recording.called # Disabled for now as recording is disabled
Tf0883e@patchTb4b4b4(Ta5d6ff"Ta5d6ffmeshchatx.src.backend.telephone_manager.TelephoneTa5d6ff"Tb4b4b4)
Tff7b72def Td2a8fftest_manual_mute_overridesTb4b4b4(
Te6edf3mock_telephone_classTb4b4b4,
Te6edf3mock_identityTb4b4b4,
Te6edf3mock_configTb4b4b4,
Te6edf3temp_storageTb4b4b4,
Tb4b4b4)Tb4b4b4:
Te6edf3mock_telephone Tff7b72= Te6edf3mock_telephone_classTff7b72.Td2a8ffreturn_value
Te6edf3tm Tff7b72= Te6edf3TelephoneManagerTb4b4b4(
Te6edf3mock_identityTb4b4b4,
Te6edf3config_managerTff7b72=Te6edf3mock_configTb4b4b4,
Te6edf3storage_dirTff7b72=Te6edf3temp_storageTb4b4b4,
Tb4b4b4)
Te6edf3tmTff7b72.Td2a8ffinit_telephoneTb4b4b4(Tb4b4b4)
T8b949e# Test transmit mute
Te6edf3tmTff7b72.Td2a8ffmute_transmitTb4b4b4(Tb4b4b4)
Tff7b72assert Te6edf3tmTff7b72.Td2a8fftransmit_muted Tff7b72is Tff7b72True
Te6edf3mock_telephoneTff7b72.Td2a8ffmute_transmitTff7b72.Td2a8ffassert_called_onceTb4b4b4(Tb4b4b4)
Te6edf3tmTff7b72.Td2a8ffunmute_transmitTb4b4b4(Tb4b4b4)
Tff7b72assert Te6edf3tmTff7b72.Td2a8fftransmit_muted Tff7b72is Tff7b72False
Te6edf3mock_telephoneTff7b72.Td2a8ffunmute_transmitTff7b72.Td2a8ffassert_called_onceTb4b4b4(Tb4b4b4)
T8b949e# Test receive mute
Te6edf3tmTff7b72.Td2a8ffmute_receiveTb4b4b4(Tb4b4b4)
Tff7b72assert Te6edf3tmTff7b72.Td2a8ffreceive_muted Tff7b72is Tff7b72True
Te6edf3mock_telephoneTff7b72.Td2a8ffmute_receiveTff7b72.Td2a8ffassert_called_onceTb4b4b4(Tb4b4b4)
Te6edf3tmTff7b72.Td2a8ffunmute_receiveTb4b4b4(Tb4b4b4)
Tff7b72assert Te6edf3tmTff7b72.Td2a8ffreceive_muted Tff7b72is Tff7b72False
Te6edf3mock_telephoneTff7b72.Td2a8ffunmute_receiveTff7b72.Td2a8ffassert_called_onceTb4b4b4(Tb4b4b4)
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────